<!--
    简单的临时表格方案，需传入model与data数据
    只负责数据显示
-->
<template>
	<div class="table-wrapper table-fiexd-action" :class="{unselect:unselect}">
		<Spin size="large" fix v-show="loading"></Spin>
		<div class="table-data-wrapper">
			<table ref="data_table" class="table" :class="tableClass">
				<thead>
					<slot name="thead">
						<tr>
							<th class="check-cell" @click="checkAllRow($event)" v-if="hasCheck">
								<Checkbox v-show="!singleSelect" v-model="checkAll"></Checkbox>
							</th>
							<th v-for="col in orderFields" :key="col.code" v-if="col.listpos!==false" :data-code="col.code">
								{{col.name}}
							</th>
						</tr>
					</slot>
				</thead>
				<tbody>
					<slot name="tbody">
						<tr v-if="!tableData || !tableData.length">
							<td colspan="999" class="text-nodata">
								暂无数据
							</td>
						</tr>
						<tr v-else @dblclick="dbTrigger(index)" v-for="(row,index) in tableData" :key="row.id" :style="rowsStyle[index]" :class="{[ativeClass]:checkList[index]}" @click="checkTableRow($event,index)">
							<td class="check-cell" v-if="hasCheck" @click="checkRow($event,index)">
								<Checkbox v-model="checkList[index]"></Checkbox>
							</td>
							<td v-for="col in orderFields" :key="col.code" v-if="col.listpos!==false">
								<div v-if="!extRender[col.code]" v-height-light="col.rangeset && col.rangeset.lang" class="field" :class="fieldClass(row[col.code],col.code)" v-html="renderData(row[col.code],col.code,row)"></div>
								<component v-else-if="extRender[col.code].component" :is="extRender[col.code].component" :data="row[col.code]" :field="col" :row="row" :option="extRender[col.code]" :index="index" :model="col"></component>
							</td>
						</tr>

					</slot>
				</tbody>
				<tfoot v-if="false">
					<slot name="tfoot">
						<th></th>
					</slot>
				</tfoot>
			</table>
		</div>
		<div class="table-action-wrapper" v-if="hasInlineAction">
			<table ref="action_table" v-if="tableData && tableData.length && hasTableAction" class="table table-action" :class="tableClass">
				<thead>
					<tr>
						<th>
							操作
						</th>
					</tr>
				</thead>
				<tbody>
					<tr v-for="(row,index) in tableData" :key="row.id" :style="rowsStyle[index]" :class="{[ativeClass]:checkList[index]}" @click="checkTableRow($event,index)">
						<td v-if="tableModel.actions && tableModel.actions.length">
							<div class="text-right">
								<InlineAction v-show="inlineActionStatus[action.code]?inlineActionStatus[action.code].show:true" v-for="action in tableModel.actions" :index="index" :model="action" :key="action.code" :row="row"></InlineAction>
							</div>
						</td>
					</tr>
				</tbody>
			</table>
		</div>
	</div>
</template>

<script>
import $ from "@/common";
import Field from "field/type";
import Render from "@/common/render";
import InlineAction from "action/inlineAction";
import HeightLight from "@/directives/height-light";
import Scroller from "@/element/scrollbar/h-scrollBar";
export default {
  name: "gridTable",
  props: {
    unselect: {
      default: false
    },
    hasCheck: {
      default: true
    },
    hasAction: {
      default: false
    },
    loading: {
      default: false
    },
    model: {},
    //点击可选中行
    rowCheckMode: {
      default: false
    },
    //选中行的类名
    ativeClass: {
      default: "active"
    },
    data: {
      default: () => []
    },
    keyWord: {
      type: String,
      default: ""
    },
    size: {
      default: null
    },
    //单选列表
    singleSelect: {
      default: false
    },
    //表单默认值，主要为子表服务
    defaultData: {},
    hasInlineAction: {
      default: true
    }
  },
  data() {
    return {
      checkAll: false,
      tableModel: {},
      tableData: [],
      initData: [],
      checkList: [],
      fieldList: [],
      extRender: {},
      //用以同步action与data行的高度
      rowsStyle: [],
      //行内状态数据吗，用于从外部强制控制inlineAction的状态
      //临时方案，待改进
      inlineActionStatus: {}
    };
  },
  watch: {
    data: {
      immediate: true,
      handler() {
        this.$set(this, "tableData", this.data);
        this.$set(this, "initData", this.data);
        this.$set(this, "checkList", []);
        this.$nextTick(() => {
          this.updateTableStyle();
        });
      }
    },
    keyWord(val) {
        if (val) {
            this.tableData = [];
            this.tableData = this.initData.filter(v => {
            let result = Object.keys(v).some(k => {
                return v[k].toString().indexOf(val) >= 0
            }) 
            if (result) {
              return v;
            }   
		});
      } else {
           this.tableData = this.initData.slice(0)
      }
    },
    checkList(v) {
      this.$emit("checkChange", v);
    },
    tableModel: {
      immediate: true,
      handler(tableModel) {
        this.dataRender = {};
        this.fieldList = $.propMap(tableModel.fields, "code");
        for (let i in tableModel.fields) {
          let field = tableModel.fields[i];
          if (Field[field.type] && Field[field.type].render) {
            this.dataRender[field.code] = Field[field.type].render(field);
          }
          if (field.tpl) {
            this.dataRender[field.code] = (code, row) => {
              return Render.tpl($.composeValue(field.tpl, row), field, row);
            };
          }
        }
      }
    },
    model(v) {
      this.$set(this, "tableModel", v);
    }
  },
  computed: {
    actionShow() {
      return this.tableData && this.tableData.length && this.hasTableAction;
    },
    hasTableAction() {
      if (this.tableModel.actions && this.tableModel.actions.length) {
        for (let i in this.tableModel.actions) {
          let action = this.tableModel.actions[i];
          if (
            action.locate === "inline" &&
            (this.inlineActionStatus[action.code]
              ? this.inlineActionStatus[action.code].show
              : true)
          ) {
            if (
              !(
                action.type === "webcall" &&
                action.param &&
                action.param.field_phone
              )
            ) {
              return true;
            }
          }
        }
        return false;
      }
      return false;
    },
    orderFields() {
      return (this.tableModel.fields || [])
        .filter(v => {
          return v.listpos !== 0 && v.scope !== "param";
        })
        .sort((a, b) => {
          return a.listpos - b.listpos;
        });
    },
    tableClass() {
      var classSet = {};
      if (this.size) {
        classSet[`table-${this.size}`] = true;
      }
      return classSet;
    },
    hasData() {
      return this.tableData && this.tableData.length;
    }
  },
  created() {
    this.$owner = $.getParent(this, "actionOwner", true);
    if (this.model) {
      this.$set(this, "tableModel", this.model);
    } else {
      if (this.data && this.data.length) {
        var tempModel = {
          fields: []
        };
        for (let i in this.data[0]) {
          tempModel.fields.push({
            code: i,
            name: i
          });
        }
        this.$set(this, "tableModel", tempModel);
        this.$set(this, "tableData", this.data);
      }
    }
    this.resizeHanler = () => {
      this.updateTableStyle;
    };
    window.addEventListener("resize", this.resizeHanler);
  },
  destroyed() {
    window.removeEventListener("resize", this.resizeHanler);
  },
  methods: {
    //d为标记类型，d为true时为数据表，false为action表
    dbTrigger(index) {
      this.$emit("dbTrigger", index);
    },
    //字段组件触发自定义事件
    fieldTrigger(field, index, e) {
      this.$emit("fieldTrigger", {
        field,
        index,
        code: field.code,
        data: e
      });
    },
    trStyle(i, d) {
      var style = {};
      if (!this.dataRows) {
        this.getRowsElement();
      }
      if (
        this.dataRows &&
        this.actionRows &&
        this.dataRows[i] &&
        this.actionRows[i]
      ) {
        if (d) {
          if (this.dataRows[i].offsetHeight < this.actionRows[i].offsetHeight) {
            style.height = this.actionRows[i].offsetHeight + "px";
          }
        } else {
          if (this.actionRows[i].offsetHeight < this.dataRows[i].offsetHeight) {
            style.height = this.actionRows[i].offsetHeight + "px";
          }
        }
        var heightNow = d
          ? this.dataRows[i].style.height
          : this.actionRows[i].style.height;
        if (!style.height && heightNow) {
          style.height = heightNow;
        }
      }
      return style;
    },
    //清空方法
    clear: function() {
      this.checkAll = false;
      this.$set(this, "checkList", []);
      this.$set(this, "tableData", []);
    },
    renderData: function(value, code, row) {
      if (this.dataRender && this.dataRender[code]) {
        return this.dataRender[code](value, row);
      } else {
        return value;
      }
    },
    fieldClass(value, code) {
      var res = {};
      var field = this.fieldList[code];
      if (field) {
        if (field.render && field.render.class_name) {
          if (field.render.class_name[value]) {
            res[field.render.class_name[value]] = true;
          }
        } else {
          res["field-" + field.type] = true;
          if (field.type === "memo" && value && value.length) {
            res["field-value"] = true;
          }
        }
        if (field.param && field.param.enable_copy) {
          res["field-copy"] = true;
          res["click-to-copy"] = true;
        }
      }
      return res;
    },
    //临时处理，待完善
    actionTrigger(data) {
      if (this.$parent.actionTrigger) {
        return this.$parent.actionTrigger(data);
      } else {
        return this.$emit("actionTrigger", data);
      }
    },
    checkTableRow(e, i) {
      if (this.rowCheckMode) {
        if (!this.checkList[i]) {
          this.checkRow(e, i, true);
        }
      }
    },
    //点击单元格选中行
    checkRow(e, i, isRow) {
      //判断点击元素，阻止点击checkbox时重复触发改变
      if (this.singleSelect && !this.checkList[i]) {
        //单选处理
        this.$set(this, "checkList", []);
      }
      if (e.target === e.currentTarget || isRow) {
        this.$set(this.checkList, i, !this.checkList[i]);
      }
      if (this.checkList[i] && this.checkAll) {
        this.checkAll = false;
      }
      this.$emit("rowCheck", {
        value: this.checkList[i],
        index: i,
        id: this.data[i].id
      });
    },
    //行全选
    checkAllRow(e) {
      var val = !this.checkAll;
      if (e.target === e.currentTarget) {
        this.checkAll = !this.checkAll;
      } else {
      }
      var list = [];
      for (var i = 0; i < this.tableData.length; i++) {
        list[i] = val;
      }
      this.$set(this, "checkList", list);
    },
    getSelectedDataRow() {
      for (var i in this.checkList) {
        if (this.checkList[i]) {
          return this.tableData[i];
        }
      }
    },
    getSelectedDataRows() {
      var list = [];
      for (var i in this.checkList) {
        list.push(this.tableData[i]);
      }
      return list;
    },
    getSelectedIds() {
      var list = [];
      for (var i in this.checkList) {
        if (this.checkList[i] && this.tableData[i].id !== undefined) {
          list.push(this.tableData[i].id);
        }
      }
      return list;
    },
    getSelectedIndex() {
      for (var i in this.checkList) {
        if (this.checkList[i]) {
          return i;
        }
      }
    },
    importTableComponents(data) {
      $.setProp(this.$options.components, data);
    },
    addExtRender(data = {}) {
      this.$set(this, "extRender", $.setObj(data, this.extRender));
    },
    setInlineActionStatus(command) {
      this.$set(
        this.inlineActionStatus,
        command.code,
        $.setObj(command, this.inlineActionStatus, [command.code])
      );
    },
    getRowsElement() {
      if (this.$refs.data_table) {
        //缓存列表变量，以便渲染列表
        this.dataRows = this.$refs.data_table.querySelectorAll("tbody>tr");
      }
      if (this.$refs.action_table) {
        this.actionRows = this.$refs.action_table.querySelectorAll("tbody>tr");
      }
    },
    updateTableStyle() {
      this.updateRowStyle();
      this.updateColumnsStyle();
    },
    updateRowStyle() {
      var list = [];
      this.getRowsElement();
      if (this.dataRows && this.actionRows) {
        Array.prototype.forEach.call(this.dataRows, (dataRow, index) => {
          var actionRow = this.actionRows[index];
          var height;
          if (actionRow) {
            if (actionRow.offsetHeight > dataRow.offsetHeight) {
              height = actionRow.offsetHeight;
            } else {
              height = dataRow.offsetHeight;
            }
          }
          if (height) {
            list[index] = {
              height: height + "px"
            };
          }
        });
      }
      this.$set(this, "rowsStyle", list);
    },
    updateColumnsStyle() {}
  },
  //刷新时更新数据行缓存
  updated() {},
  directives: {
    HeightLight
  },
  components: {
    InlineAction,
    Scroller
  }
};
</script>

<style lang="less">
.table-wrapper {
  .table-box {
    flex: 1;
    display: flex;
  }
}
.table-wrapper.unselect {
  .table-data-wrapper {
    table.table {
      tr > td {
        -webkit-touch-callout: none;
        user-select: none;
      }
    }
  }
}
</style>
